/*
** Alice is this node, Bob is the other node.
** Key exchange sequence of events when Alice initiates:
** 1. Alice sends ELGAMAL_PUBLIC_KEY_REQUEST to Bob
** 2. Bob receives message and replies with ELGAMAL_PUBLIC_KEY_RESPONSE
** 3. Alice encrypts shared key with Bob's public key and sends encryption as ELGAMAL_SEND_DATA
** 4. Bob receives message and replies with ELGAMAL_DATA_ACK
*/

#ifndef ELGAMAL_HPP
#define ELGAMAL_HPP

#include "cryptoUtil.h"

// encryption constants
static const unsigned int prime = 0xFFFFFFFF - 4;			// 2^32 - 5
static const unsigned int montgomery_N = 0xFFFFFFFF;		// 2^32 - 1
static const unsigned long long montgomery_R = 0x100000000LL;	// 2^32
static const unsigned int generator = 2;

// ciphertext representation
typedef struct
{
	unsigned int c1;
	unsigned int c2;
} Ciphertext;

// key exchange messages
#define ELGAMAL_PUBLIC_KEY_REQUEST 	1
#define ELGAMAL_PUBLIC_KEY_RESPONSE 	2
#define ELGAMAL_SEND_DATA	 	3
#define ELGAMAL_DATA_ACK		4

// readiness states
#define ELGAMAL_EXCHANGING_KEY		100
#define ELGAMAL_WAITING			101
#define ELGAMAL_READY			102

typedef struct
{
	unsigned char macAddr[6];
	unsigned int publicKey;
	unsigned int state;
	unsigned int sharedKey;
} Peer;

// function definitions
unsigned int calculateGCD(unsigned int, unsigned int);
unsigned int computeRandomNumber(void);
unsigned int modularExponentiation(unsigned int, unsigned int, unsigned int );
unsigned int generatePrivateKey(void);
unsigned int generatePublicKey(unsigned int);
Ciphertext elGamalEncrypt( unsigned int, unsigned int );
unsigned int elGamalDecrypt( unsigned int, Ciphertext );
void handleElGamal( PCryptoPacket, WLANHeader * );
void initiateElGamal(void);
int compareMacAddrs( unsigned char *, unsigned char * );
void printElGamalPeerTable(void);
void clearElGamalPeerTable(void);

#endif
